#include <stdio.h>
#include <unistd.h>
#include <syslog.h>


#define is_changed(c)                                                           \
do {                                                                            \
    if(t > 0 && prev_##c != c) {                                                \
        int ntmp = c - prev_##c;                                                \
        n = snprintf(printc+size, LEN-size, "%s %s%d, ",#c,ntmp>0?"+":"",ntmp); \
        size += n;                                                              \
        changed = 1;                                                            \
    }                                                                           \
    prev_##c = c;                                                               \
}while(0)



int main()
{
    unsigned long total, used, mfree, shared, buffers, cached;
    unsigned long prev_total, prev_used, prev_mfree, prev_shared, prev_buffers, prev_cached;
    char buf[100];
#define LEN 1024
    char printc[LEN] = {0};
    size_t size = 0;
    int n;
    int changed = 0;
    FILE* fp;
    int t = 0;

    while(1) {
        fp = fopen("/proc/meminfo", "r");

        if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) {
            fgets(buf, sizeof(buf), fp);    /* skip first line */

            fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
                &total, &used, &mfree, &shared, &buffers, &cached);
            /* convert to kilobytes */
            used /= 1024;
            mfree /= 1024;
            shared /= 1024;
            buffers /= 1024;
            cached /= 1024;
            total /= 1024;
        } else {
            /*
             * Revert to manual parsing, which incidentally already has the
             * sizes in kilobytes. This should be safe for both 2.4 and
             * 2.6.
             */
            fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);

            /*
             * MemShared: is no longer present in 2.6. Report this as 0,
             * to maintain consistent behavior with normal procps.
             */
            if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
                shared = 0;

            fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
            fscanf(fp, "Cached: %lu %s\n", &cached, buf);

            used = total - mfree;
        }
        fclose(fp);

        size = 0;
        changed = 0;

        n = snprintf(printc+size, LEN-size, "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
            used, mfree, shared, buffers, cached);
        size += n;

        n = snprintf(printc+size, LEN-size, "  | ");
        size += n;

        is_changed(total);
        is_changed(used);
        is_changed(mfree);
        is_changed(shared);
        is_changed(buffers);
        is_changed(cached);

        n = snprintf(printc+size, LEN-size, "|");
        size += n;

        printf("%s\n", printc);
        if(t == 0 || changed) {
            syslog(LOG_INFO, "%s", printc);
        }

        t ++;
        sleep(1);
    }
    
    return 0;
}

